package com.shenmazong.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.shenmazong.entity.TbArticle;
import com.shenmazong.entity.TbCounter;
import com.shenmazong.mapper.TbArticleMapper;
import com.shenmazong.mapper.TbCounterMapper;
import com.shenmazong.service.TbArticleService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shenmazong.utils.ResultResponse;
import com.shenmazong.vo.ArticleVo;
import com.shenmazong.vo.ListParamVo;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.shenmazong.vo.ReturnVo;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.document.Document;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import rx.internal.operators.OnSubscribeSwitchIfEmpty;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 技术文章表   ——> John 服务实现类
 * </p>
 *
 * @author 还怕大雨吗
 * @since 2021-09-18
 */
@Service
public class TbArticleServiceImpl extends ServiceImpl<TbArticleMapper, TbArticle> implements TbArticleService {

    @Resource
    private TbArticleMapper tbArticleMapper;

    @Resource
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Resource
    private TbCounterMapper tbCounterMapper;

    @Resource
    private StringRedisTemplate stringRedisTemplate;



    /***
     * @description 查询所有技术文章
     * @params [listParamVo]
     * @return com.shenmazong.utils.ResultResponse
     * @author -还怕大雨吗
     * @date 2021/9/18 10:39
     */
    @Override
    @Cacheable(value = "selectArticle")
    public ResultResponse selectArticle(ListParamVo listParamVo) {
        IPage<ArticleVo> list = tbArticleMapper.selectbyArticle(
                new Page<TbArticle>(listParamVo.getCurrent(),listParamVo.getSize()),
                listParamVo.getParamMap().get("title"),listParamVo.getParamMap().get("type"),
                 listParamVo.getParamMap().get("teachid"), listParamVo.getParamMap().get("userName")
        );
        return ResultResponse.SUCCESS(list);
    }





    /***
     * @description 删除自己的技术文章
     * @params [listParamVo]
     * @return com.shenmazong.utils.ResultResponse
     * @author -还怕大雨吗
     * @date 2021/9/18 10:39
     */
    @Override
    @CacheEvict(value = "selectArticle",allEntries = true)
    public ResultResponse deleteArticle(Long listParamVo) {
        TbArticle tbArticle = tbArticleMapper.selectById(listParamVo);
        if (tbArticle == null){
            return ResultResponse.SUCCESS("删除成功，请刷新页面后再试");
        }
        tbArticleMapper.deleteById(listParamVo);
        return ResultResponse.SUCCESS();
    }

    /***
     * @description 发布文章
     * @params [listParamVo]
     * @return com.shenmazong.utils.ResultResponse
     * @author -还怕大雨吗
     * @date 2021/9/18 11:23
     */
    @Override
    @CacheEvict(value = "selectArticle",allEntries = true)
    public ResultResponse insertArticle(TbArticle listParamVo) {
        try {
            tbArticleMapper.insert(listParamVo);
            TbArticle tbArticle = tbArticleMapper.selectOne(
                    new QueryWrapper<TbArticle>().lambda().eq(TbArticle::getArticleTitle, listParamVo.getArticleTitle())
            );

            TbCounter tbCounter = new TbCounter();
            tbCounter.setArticleId(tbArticle.getArticleId());
            tbCounterMapper.insert(tbCounter);


        } catch (Exception e) {
//            e.printStackTrace();
            return ResultResponse.FAILED("新增失败，稍后重试");
        }
        return ResultResponse.SUCCESS();
    }


    /***
     * @description 修改文章
     * @params [listParamVo]
     * @return com.shenmazong.utils.ResultResponse
     * @author -还怕大雨吗
     * @date 2021/9/18 11:27
     */
    @Override
    @CacheEvict(value = "selectArticle",allEntries = true)
    public ResultResponse updateArticle(TbArticle listParamVo) {
        TbArticle articleID = tbArticleMapper.selectOne(
                new QueryWrapper<TbArticle>().lambda().eq(TbArticle::getArticleId,listParamVo.getArticleId()).last("limit 1")
        );

        articleID.setArticleTitle(listParamVo.getArticleTitle());
        articleID.setArticleType(listParamVo.getArticleType());
        articleID.setArticleShow(listParamVo.getArticleShow());

        tbArticleMapper.updateById(articleID);

        return ResultResponse.SUCCESS();
    }

    @Override
    public ResultResponse selectESTbo(ListParamVo listParamVo) {
        List<ArticleVo> list = new ArrayList<>();
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.preTags("<b>").postTags("</b>").field("articleTitle");
        Object title = listParamVo.getParamMap().get("title");
        Object type = listParamVo.getParamMap().get("type");
        if (title!=null && !title.equals("")) {
            MultiMatchQueryBuilder content = QueryBuilders.multiMatchQuery(title, "articleTitle");
            boolQueryBuilder.must(content);
        }
        if (type!=null){
            MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("articleType", type);
            boolQueryBuilder.must(matchQueryBuilder);
        }
        Pageable pageable = PageRequest.of(listParamVo.getCurrent()-1 , listParamVo.getSize());
        NativeSearchQuery build = builder.withQuery(boolQueryBuilder)
                .withHighlightBuilder(highlightBuilder)
                .withPageable(pageable)
                .build();
        SearchHits<ArticleVo> search = elasticsearchRestTemplate.search(build, ArticleVo.class);
        List<SearchHit<ArticleVo>> searchHits = search.getSearchHits();
        searchHits.forEach(e->{
            ArticleVo content = e.getContent();
            if (e.getHighlightField("articleTitle").size()>0){
                content.setArticleTitle(e.getHighlightField("articleTitle").get(0));
            }
            list.add(content);
        });
        long totalHits = search.getTotalHits();
        ReturnVo returnVo = new ReturnVo();
        returnVo.setHits(totalHits);
        returnVo.setList(list);
        return ResultResponse.SUCCESS(returnVo);
    }


    /***
     * @description 定时同步数据到Es中
     * @params []
     * @return void
     * @author -还怕大雨吗
     * @date 2021/9/25 11:27
     */
    @Scheduled(cron = "0 0/1 * * * ? ")
    public void TimeEs(){
        if (!elasticsearchRestTemplate.indexOps(ArticleVo.class).exists()){
            elasticsearchRestTemplate.indexOps(ArticleVo.class).create();
            Document mapping = elasticsearchRestTemplate.indexOps(ArticleVo.class).createMapping();
            elasticsearchRestTemplate.indexOps(ArticleVo.class).putMapping(mapping);
        }
        List<ArticleVo> synces = tbArticleMapper.synces();
        elasticsearchRestTemplate.save(synces);


        try {
            synces.forEach(e->{
                TbArticle tbArticle = tbArticleMapper.selectById(e.getArticleId());
                tbArticle.setEsStatus(1);
                tbArticleMapper.updateById(tbArticle);
            });
        } catch (Exception e) {
            System.out.println("Es同步Mysql状态失败，请管理员检查 = " + e);
            e.printStackTrace();
        }

    }



}
